﻿using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace MeTool
{
    /// <summary>
    /// 此类用于密码文本的加密和解密
    /// </summary>
    /// <remarks></remarks>
    public static class PasswordHelper
    {
        private static byte[] TruncateHash(string key, int length)
        {
            using (var sha = SHA256.Create())
            {
                byte[] keyBytes = Encoding.Unicode.GetBytes(key);
                byte[] hash = sha.ComputeHash(keyBytes);
                var dBytes = new byte[length];
                Array.Copy(hash, 0, dBytes, 0, length);
                return dBytes;
            }
        }

        /// <summary>
        /// 字符串加密
        /// </summary>
        /// <param name="key">用来加密的密钥</param>
        /// <param name="plaintext">被处理的文本</param>
        /// <returns>加密后的文本</returns>
        /// <remarks></remarks>
        public static string EncryptData(this string key, string plaintext)
        {
            TripleDes.Key = TruncateHash(key, TripleDes.KeySize / 8);
            TripleDes.IV = TruncateHash("", TripleDes.BlockSize / 8);
            byte[] plaintextBytes = Encoding.Unicode.GetBytes(plaintext);
            MemoryStream ms = new MemoryStream();
            CryptoStream encStream = new CryptoStream(ms, TripleDes.CreateEncryptor(), CryptoStreamMode.Write);
            encStream.Write(plaintextBytes, 0, plaintextBytes.Length);
            encStream.FlushFinalBlock();
            encStream.Dispose();
            return Convert.ToBase64String(ms.ToArray());
        }

        /// <summary>
        /// 字符串解密, 如果不成功返回 Null
        /// </summary>
        /// <param name="key"></param>
        /// <param name="encryptedtext"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static string DecryptData(this string key, string encryptedText)
        {
            TripleDes.Key = TruncateHash(key, TripleDes.KeySize / 8);
            TripleDes.IV = TruncateHash("", TripleDes.BlockSize / 8);
            byte[] dBytes;
            try
            {
                dBytes = Convert.FromBase64String(encryptedText);
            }
            catch (Exception)
            {
                return null;
            }
            MemoryStream ms = new MemoryStream();
            //实测必须把using包含在try里面,才能截获异常,可能是因为异常是在变量被释放的时候抛出的
            try
            {
                using (var decStream = new CryptoStream(ms, TripleDes.CreateDecryptor(), CryptoStreamMode.Write))
                {
                    decStream.Write(dBytes, 0, dBytes.Length);
                    decStream.FlushFinalBlock();
                    return Encoding.Unicode.GetString(ms.ToArray());
                };
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <summary>
        /// 创建一个密码
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static string SHACreate(this string text)
        {
            string SHACreate;
            using (var dSha = SHA256.Create())
            {
                byte[] dBytes = dSha.ComputeHash(Encoding.Unicode.GetBytes(text));
                SHACreate = BitConverter.ToString(dBytes);
            }
            return SHACreate;
        }

        /// <summary>
        /// 创建一个密码
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static byte[] SHACreateEx(this string text)
        {
            using (var dSha = SHA256.Create())
            {
                return dSha.ComputeHash(Encoding.Unicode.GetBytes(text));
            }
        }

        /// <summary>
        /// 比较用户输入的密码是否与已经编码的密码相符
        /// </summary>
        /// <param name="inputText"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static bool SHAComp(this string inputText, string password)
        {
            using (var dSha = SHA256.Create())
            {
                byte[] dBytes = dSha.ComputeHash(Encoding.Unicode.GetBytes(inputText));
                return BitConverter.ToString(dBytes) == password;
            }
        }

        /// <summary>
        /// 比较用户输入的密码是否与已经编码的密码相符
        /// </summary>
        /// <param name="inputText"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public static bool SHAComp(this string inputText, byte[] password)
        {
            using (var dSha = SHA256.Create())
            {
                byte[] dBytes = dSha.ComputeHash(Encoding.Unicode.GetBytes(inputText));
                return BitConverter.ToString(dBytes) == BitConverter.ToString(password);
            }
        }

        private static readonly TripleDESCryptoServiceProvider TripleDes = new TripleDESCryptoServiceProvider();
    }
}
